#include <stdio.h>

// 可变参数宏的定义
// 注意：__VA_ARGS__ 是一个特殊的宏，它代表着所有可变参数。带有##可以在VA_ARGS为空时也能正常工作。
#define LOG(format, ...) printf(format, ##__VA_ARGS__)

void test1()
{
    LOG("Hello, world! - %d\n", 123);
}

// C语言中不定参数函数的使用
#include <stdarg.h>
#include <stdlib.h>
void my_printf(const char *format, ...)
{
    va_list args;
    va_start(args, format);  // 获取指定参数的地址，并将其指向第一个可变参数
    char *str = nullptr;
    int ret = vasprintf(&str, format, args);
    if (ret != -1)
    {
        printf("%s", str);
        free(str);
    }
    va_end(args);  // 释放args占用的内存
}
// va_arg()函数的使用
void num_print(const char *format, int num, ...)
{
    va_list args;
    va_start(args, num);
    my_printf(format);
    for(int i = 0; i < num; i++)
    {
        my_printf("%d ", va_arg(args, int));  // va_arg()的第二个参数需要和参数列表中的类型一致
    }
    my_printf("\n");
    va_end(args);
}
void test2()
{
    my_printf("Hello, world! - %d\n", 123);

    num_print("num_print: %d\n", 3, 1, 2, 3);
}

// C++中不定参数函数的使用
#include <iostream>
void print_cpp()  // 需要设定一个与可变参数函数同名的空参数函数，用于编译器展开终止
{
    std::cout << "\n";
}
template<typename T, typename ...Args>
void print_cpp(T&& first, Args&& ...args)
{
    std::cout << first << "\n";
    if(sizeof ...(args) > 0)  // 递归调用, 当可变参数为空时，注意额外处理
    {
        print_cpp(std::forward<Args>(args)...);
    }
    // else  // 有print_cpp()函数的调用，不需要额外处理
    // {
    //     print_cpp();
    // }
}
void test3()
{
    print_cpp("快来", "数一数：", 1, 2, 3, 4, 5);
}

int main()
{
    test1();
    printf("************************\n");
    test2();
    printf("************************\n");
    test3();
    printf("************************\n");
    return 0;
}
